home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / utility-src / lpr.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-08  |  5.0 KB  |  230 lines  |  [TEXT/EMAC]

  1. /*
  2.  * Copyright (C) 1993, 1994 Marc Parmet.
  3.  * This file is part of the Macintosh port of GNU Emacs.
  4.  *
  5.  * GNU Emacs is distributed in the hope that it will be useful,
  6.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  7.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  8.  * GNU General Public License for more details.
  9.  */
  10.  
  11. #include <MacHeaders>
  12. #include <Folders.h>
  13. #include <Script.h>
  14. #include "getopt.h"
  15. #include "stdio.h"
  16.  
  17. static char print_format,border_rect,need_page_setup;
  18. static ProcessSerialNumber psn;
  19.  
  20. static int
  21. launch_daemon(int *we_started_it)
  22. {
  23.     short err;
  24.     FSSpec spec;
  25.     LaunchParamBlockRec lpb;
  26.  
  27.     err = unixfn2FSSpec("/bin/Print Daemon",&spec,0);
  28.     if (err) return err;
  29.  
  30.     lpb.launchBlockID = extendedBlock;
  31.     lpb.launchEPBLength = extendedBlockLen;
  32.     lpb.launchFileFlags = 0;
  33.     lpb.launchControlFlags = launchContinue | launchNoFileFlags | launchDontSwitch;
  34.     lpb.launchAppSpec = &spec;
  35.     lpb.launchAppParameters = 0L;
  36.     
  37.     err = LaunchApplication(&lpb);
  38.     psn = lpb.launchProcessSN;
  39.     *we_started_it = (lpb.launchPreferredSize != 0);
  40.     return err;
  41. }
  42.  
  43. static void
  44. send_event(long class,long type,...)
  45. {
  46.     short err;
  47.     long *others,keyword;
  48.     AEDesc target,*desc;
  49.     AppleEvent event,reply;
  50.     char have_target,have_event,have_reply;
  51.  
  52.     have_target = have_event = have_reply = 0;
  53.  
  54.     err = AECreateDesc(typeProcessSerialNumber,&psn,
  55.                        sizeof(ProcessSerialNumber),&target);
  56.     if (err) goto bail;
  57.     have_target = 1;
  58.     err = AECreateAppleEvent(class,type,&target,
  59.                              kAutoGenerateReturnID,kAnyTransactionID,&event);
  60.     if (err) goto bail;
  61.     have_event = 1;
  62.  
  63.     others = &type+1;
  64.     while (others[0] != 0) {
  65.         desc = (AEDesc *)others[0];
  66.         keyword = others[1];
  67.         err = AEPutParamDesc(&event,keyword,desc);
  68.         if (err) goto bail;
  69.         others += 2;
  70.     }
  71.  
  72.     // kAEWaitReply and kAESwitchLayer are both required to bring the printing
  73.     // dialog box to the front immediately without using the notification manager.
  74.     // An idle or filter proc here isn't really possible, because we don't have
  75.     // direct access to the event handlers of Emacs.
  76.     err = AESend(&event,&reply,kAEWaitReply | kAECanInteract | kAECanSwitchLayer,
  77.                  kAENormalPriority,kAEDefaultTimeout,0,0);
  78.     if (err) goto bail;
  79.     have_reply = 1;
  80.  
  81.  bail:
  82.     if (have_target) AEDisposeDesc(&target);
  83.     if (have_event) AEDisposeDesc(&event);
  84.     if (have_reply) AEDisposeDesc(&reply);
  85.     return;
  86. }
  87.  
  88. static void
  89. kill_daemon(void)
  90. {
  91.     send_event(kCoreEventClass,kAEQuitApplication,0);
  92. }
  93.  
  94. static void
  95. print_file(FSSpec *spec)
  96. {
  97.     short err;
  98.     AEDesc desc;
  99.  
  100.     err = AECreateDesc(typeFSS,spec,sizeof(FSSpec),&desc);
  101.     if (err) return;
  102.     send_event(kCoreEventClass,kAEPrintDocuments,&desc,keyDirectObject,0);
  103.     AEDisposeDesc(&desc);
  104. }
  105.  
  106. static void
  107. reset_options(void)
  108. {
  109.     send_event('EMAC','rset',0);
  110. }
  111.  
  112. static void
  113. send_option(char *name,...)
  114. {
  115.     short err;
  116.     AEDescList list;
  117.  
  118.     err = AECreateList(0L,0,0,&list);
  119.     if (err) return;
  120.     err = AEPutPtr(&list,0,typeChar,name,strlen(name));
  121.     if (err) goto bail;
  122.     
  123.     if (!strcmp(name,"p") || !strcmp(name,"R")) {
  124.         Boolean k = ((int *)&name)[1];
  125.         err = AEPutPtr(&list,0,typeBoolean,&k,sizeof(k));
  126.         if (err) goto bail;
  127.     }
  128.     
  129.     send_event('EMAC','opts',&list,keyDirectObject,0);
  130.  
  131.  bail:
  132.     AEDisposeDesc(&list);
  133.     return;
  134. }
  135.  
  136. static void
  137. do_page_setup(void)
  138. {
  139.     send_event('EMAC','pgst',0);
  140. }
  141.  
  142. static int
  143. copy_stdin_to_tempfile(FSSpec *spec,int *filelen)
  144. {
  145.     int fd;
  146.     long n;
  147.     char p[256];
  148.     short err,refNum;
  149.     
  150.     err = FindFolder(kOnSystemDisk,kTemporaryFolderType,kCreateFolder,
  151.                      &spec->vRefNum,&spec->parID);
  152.     if (err) return err;
  153.     pstrcpy(spec->name,"\plpr standard input");
  154.     err = FSpCreate(spec,'EMAC','TEXT',smSystemScript);
  155.     if (err && err != dupFNErr) return err;
  156.     err = FSpOpenDF(spec,fsWrPerm,&refNum);
  157.     if (err) { FSpDelete(spec); return err; }
  158.     err = SetEOF(refNum,0);
  159.     if (err) { FSpDelete(spec); return err; }
  160.     
  161.     *filelen = 0;
  162.     fd = fileno(stdin);
  163.     while (1) {
  164.         n = read(fd,p,sizeof(p));
  165.         if (n == 0) break;
  166.         if (n == -1) { FSClose(refNum); FSpDelete(spec); return err; }
  167.         err = FSWrite(refNum,&n,&p);
  168.         if (err) { FSClose(refNum); FSpDelete(spec); return err; }
  169.         *filelen += n;
  170.     }
  171.     
  172.     FSClose(refNum);
  173.     return noErr;
  174. }
  175.  
  176. int
  177. main(int argc,char **argv)
  178. {
  179.     int c,k,stdin_len;
  180.     char *fname;
  181.     int err;
  182.     FSSpec spec;
  183.     int we_started_it;
  184.     int retcode = 0;
  185.     
  186.     err = launch_daemon(&we_started_it);
  187.     if (err) return err;
  188.  
  189.     while (1) {
  190.         c = getopt(argc,argv,"pRP");
  191.         if (c == EOF) break;
  192.         switch (c) {
  193.         case 'p': print_format = 1;    break;
  194.         case 'R': border_rect = 1; break;
  195.         case 'P': need_page_setup = 1; break;
  196.         }
  197.     }
  198.  
  199.     if (need_page_setup) do_page_setup();
  200.     reset_options();
  201.     send_option("p",print_format);
  202.     send_option("R",border_rect);
  203.     
  204.     k = optind;
  205.  
  206.     if (k == argc) {
  207.         copy_stdin_to_tempfile(&spec,&stdin_len);
  208.         if (stdin_len == 0) {
  209.             fprintf(stderr,"%s: Nothing to print\n",argv[0]);
  210.             retcode = 1;
  211.         }
  212.         else
  213.             print_file(&spec);
  214.         FSpDelete(&spec);
  215.     }
  216.     else {
  217.         for (; k<argc; ++k) {
  218.             fname = argv[k];
  219.             err = unixfn2FSSpec(fname,&spec,0);
  220.             if (err)
  221.                 fprintf(stderr,"%s: cannot open file '%s'\n",argv[0],fname);
  222.             else
  223.                 print_file(&spec);
  224.         }
  225.     }
  226.  
  227.     if (we_started_it) kill_daemon();
  228.     return retcode;
  229. }
  230.